package com.hpsk.enums;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.BeanUtils;

import java.io.IOException;

/**
 * @author wandoupeas
 * @date 2020/08/19
 */
public class BaseEnumDeserializer extends JsonDeserializer<BaseEnum> {

    @Override
    @SuppressWarnings("unchecked")
    public BaseEnum deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);
        String currentName = jp.currentName();
        Object currentValue = jp.getCurrentValue();
        @SuppressWarnings("rawtypes")
        Class findPropertyType = BeanUtils.findPropertyType(currentName, currentValue.getClass());
        JsonFormat annotation = (JsonFormat) findPropertyType.getAnnotation(JsonFormat.class);
        BaseEnum valueOf;
        if (annotation == null || annotation.shape() != JsonFormat.Shape.OBJECT) {
            valueOf = (BaseEnum) BaseEnum.valueOf(node.asText(), findPropertyType);
        } else {
            if (node.get("value") == null) {
                if (node.get("code") == null) {
                    try {
                        valueOf = (BaseEnum) BaseEnum.valueOf(node.asText(), findPropertyType);
                    } catch (Exception e) {
                        valueOf = (BaseEnum) BaseEnum.valueOf(node.asText().toUpperCase(), findPropertyType);
                    }
                } else {
                    try {
                        valueOf = (BaseEnum) BaseEnum.valueOf(node.get("code").asText(), findPropertyType);
                    } catch (Exception e) {
                        valueOf = (BaseEnum) BaseEnum.valueOf(StrUtil.toUnderlineCase(node.get("code").asText()).toUpperCase(), findPropertyType);
                    }
                }
            } else {
                try {
                    valueOf = (BaseEnum) BaseEnum.valueOf(node.get("value").asText(), findPropertyType);
                } catch (Exception e) {
                    valueOf = (BaseEnum) BaseEnum.valueOf(node.get("value").asText().toUpperCase(), findPropertyType);
                }
            }
        }
        return valueOf;
    }

}